package org.xi.maple.util;

import com.alibaba.fastjson.JSONObject;
import org.xi.maple.api.*;

import java.lang.reflect.ParameterizedType;
import java.util.Map;

public class PluginUtil {

    private final static Map<String, Class<?>> SOURCE_PLUGINS;
    private final static Map<String, Class<?>> TRANSFORM_PLUGINS;
    private final static Map<String, Class<?>> SINK_PLUGINS;

    static {
        SOURCE_PLUGINS = MapleServiceLoader.load(MapleSource.class);
        TRANSFORM_PLUGINS = MapleServiceLoader.load(MapleTransform.class);
        SINK_PLUGINS = MapleServiceLoader.load(MapleSink.class);
    }

    public static <T extends SourceConfig> MapleSource<T> createSource(String name, JSONObject config) throws InstantiationException, IllegalAccessException {
        return createPlugin(SOURCE_PLUGINS, name, config);
    }

    public static <T extends TransformConfig> MapleTransform<T> createTransform(String name, JSONObject config) throws InstantiationException, IllegalAccessException {
        return createPlugin(TRANSFORM_PLUGINS, name, config);
    }

    public static <T extends SinkConfig> MapleSink<T> createSink(String name, JSONObject config) throws InstantiationException, IllegalAccessException {
        return createPlugin(SINK_PLUGINS, name, config);
    }

    static <T extends MaplePlugin> T createPlugin(Map<String, Class<?>> pluginMap, String name, JSONObject config) throws InstantiationException, IllegalAccessException {
        Class<?> type = pluginMap.get(name);
        ParameterizedType genericSuperclass = (ParameterizedType) type.getGenericInterfaces()[0];
        Class<?> configType = (Class<?>) genericSuperclass.getActualTypeArguments()[0];
        T plugin = (T) type.newInstance();
        plugin.setConfig(config.toJavaObject(configType));
        return plugin;
    }
}
